package psutil

import (
	"context"
	"github.com/shirou/gopsutil/v3/cpu"
	"github.com/shirou/gopsutil/v3/disk"
	"github.com/shirou/gopsutil/v3/host"
	"github.com/shirou/gopsutil/v3/mem"
	"github.com/shirou/gopsutil/v3/net"
	bdnet "net"
	"time"

	"trusteva/app/rbac/internal/svc"
	"trusteva/app/rbac/internal/types"

	"github.com/zeromicro/go-zero/core/logx"
)

type PSUtilLogic struct {
	logx.Logger
	ctx    context.Context
	svcCtx *svc.ServiceContext
}

func NewPSUtilLogic(ctx context.Context, svcCtx *svc.ServiceContext) *PSUtilLogic {
	return &PSUtilLogic{
		Logger: logx.WithContext(ctx),
		ctx:    ctx,
		svcCtx: svcCtx,
	}
}

func (l *PSUtilLogic) PSUtil(req *types.PSUtilRo) (resp *types.PSUtilRsp, err error) {
	resp = new(types.PSUtilRsp)
	{
		n, err := host.Info()
		if err != nil {
			return nil, err
		}
		resp.Host.HostName = n.Hostname
		resp.Host.OS = n.OS
		resp.Host.KernelArch = n.KernelArch
		addrs, err := bdnet.InterfaceAddrs()
		if err != nil {
			return nil, err
		}
		for _, v := range addrs {
			if ipnet, ok := v.(*bdnet.IPNet); ok && !ipnet.IP.IsLoopback() {
				if ipnet.IP.To4() != nil {
					resp.Host.IPList = append(resp.Host.IPList, ipnet.IP.String())
				}
			}

		}
	}

	{
		cpuinfo, err := cpu.Info()
		if err != nil {
			return nil, err
		}

		physicalCnt, _ := cpu.Counts(false)
		logicalCnt, _ := cpu.Counts(true)
		resp.CPU.Cnt = len(cpuinfo)
		resp.CPU.PhysicalCnt = physicalCnt
		resp.CPU.LogicalCnt = logicalCnt

		// 取第一颗CPU
		cpuPercent, _ := cpu.Percent(time.Second, false)
		resp.CPU.Percent = cpuPercent[0]
		resp.CPU.ModeName = cpuinfo[0].ModelName
	}

	{
		v, err := mem.VirtualMemory()
		if err != nil {
			return nil, err
		}
		resp.Mem.Total = v.Total
		resp.Mem.Used = v.Used
		resp.Mem.Percent = v.UsedPercent
	}

	{
		v, _ := disk.Usage("/")
		if err != nil {
			return nil, err
		}
		resp.Disk.Total = v.Total
		resp.Disk.Used = v.Used
		resp.Disk.Percent = v.UsedPercent
	}

	{
		nv, _ := net.IOCounters(true)
		if err != nil {
			return nil, err
		}

		for _, v := range nv {
			resp.Net.BytesSent = resp.Net.BytesSent + v.BytesSent
			resp.Net.BytesRecv = resp.Net.BytesRecv + v.BytesRecv
		}
	}

	return
}
